#pragma once

// Copyright (c) 2010 Manuel Peinado Gallego <manuel.peinado@gmail.com>
// Distributed under the MIT license

// UiFollower.h : interface of the UiFollower class
//

#include "SelectionManager.h"
#include "LogManager.h"
class Ui;


// ----------------------------------------------------------------------------
// Class "UiFollower"
// ----------------------------------------------------------------------------
// Base class for classes that are interested in UI stuff in general, such
// event notifications or simply knowing about the different UI objects. 
// At the moment there are two UI objects in our system: the SelectionManager
// and the ActionManager. Classes that derive from UiFollower are associated
// with an UI instance which in turn gives them access to these two object.
// Additionally, derived class can choose (via the flags passed to the ctor.)
// to be automatically registered as listeners of the various notification
// events associated to these objects. For example, the following class is 
// a UiFollower that will be notified of selectionChanged events:
//    class Foo : public UiFollower
//    {
//         Foo() : UiFollower(UiFollowerFlag::IsSelectionListener) { }
//         
//         void bar()  
//         { 
//             // do something with inherithed m_ui member, for example
//             // access the current selection as 
//             //     m_ui->getSelectionManager().getSelection()
//         }
//     };
// As soon as you create an instance of UiFollower, you should associate it
// with a given Ui (otherwise it's m_ui member will be NULL). This is 
// accomplished via the addUiFollower of the Ui object itself. For instance:
//     Foo* theFoo = new Foo;
//     uiInstance.addUiFollower(foo);
// Ideally this mechanism would employ ref. counted pointers but that doesn't
// play nicely with MFC
// ----------------------------------------------------------------------------

class UiFollower : public SelectionChangeListener, 
                   public LogListener
{
public:
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    // Constructor flags
    enum 
    {
        ListenNothing = 0,
        IsSelectionListener = 1, 
        IsActionListener = 2,
        IsLogListener = 4
    };

    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -


    UiFollower(int flags=0);
    virtual ~UiFollower();

    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    // Don't call getUi unless you're sure that hasUi returns true
    bool hasUi() const;
    Ui& getUi();

    void setUi(Ui* ui);

    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

protected:

    // -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  
    // Changes are not really likely so this function is mostly useful
    // for subclasses that need to know when the UI becomes available 

    virtual void onUiChanged(Ui* /*newUi*/) {}

private:

    // -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  
    
    // The UI followed by this object
    Ui* m_ui;

    // -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  
    
    // The construction flags
    int m_flags;
};

